/*
 *  main.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "analex.h"
#include "ErrorManager.h"
#include "SymbolTable.hpp"
#include "Parser.h"
#include "Visitor.hpp"
#include "analSemantic.h"

 /********************************************************************
*                       Método Principal                             *
********************************************************************/
int main(int argc, char** argv){
    FILE* file = stdin;
    node_Program *Program;
/******** Visitor usado para imprimir a AST (segunda etapa do trabalho) *****************************
    VisitorASTprint *ASTprint;
*****************************************************************************************************/

    if( argc == 1 ) analexConstructor(file);
    else if ( argc == 2 ){
            int sizeArgv = strlen(argv[1]);
            char nameFile[sizeArgv+4];

            strcpy(nameFile, argv[1]);

            if(sizeArgv > 4){
                if(strcmp(&nameFile[sizeArgv - 4], ".jmm") != 0) strcat(nameFile, ".jmm");
            } else strcat(nameFile, ".jmm");

            file = fopen(nameFile, "r");

            if(file) analexConstructor(file);
            else {
                ErrorMessage(FILE_NOT_FOUND,0);
                return EXIT_FAILURE;
            }
        }

/******** Codigo para averiguação do reconhecimento de tokens (primeira etapa do trabalho) **********
    int token = 0;
    do{
        //recebe o proximo token e imprime na saida padrao stdout
        token = nextToken();
        printToken(token);
    }while( token != EOF );
****************************************************************************************************/

    parserConstructor();
    Program = program();

/******** Codigo para impressão da AST (segunda etapa do trabalho) **********************************
    ASTprint = new VisitorASTprint();
    Program->acceptVisitor(ASTprint);
****************************************************************************************************/

    semanticConstructor(Program);
    semanticDestructor();

    if(getNum_Error() > 0) ErrorMessage();
    else{
        VisitorIRTGen* ari;
        ari = new VisitorIRTGen();
        Program->acceptVisitor(ari);

        VisitorIRTPrint* ariPrint = new VisitorIRTPrint();

        VisitorIRTCanonizer* canonizer = new VisitorIRTCanonizer();

        ari->fragmentList->acceptVisitor(ariPrint);

        while(canonizer->changed) ari->fragmentList->acceptVisitor(canonizer);
        fprintf(stdout, "=> ARVORE CANONIZADA\n\n");
        ari->fragmentList->acceptVisitor(ariPrint);

        VisitorIRTAsmTranslator *asmT = new VisitorIRTAsmTranslator();
        ari->fragmentList->acceptVisitor(asmT);
        FILE *asmCode = fopen("code.asm", "w+");
        fprintf(stdout, "\n\nAssembly Code:\n\n");
        for (unsigned int i = 0; i < asmT->asmCode.size(); i++){
            fprintf(stdout, "%s\n", asmT->asmCode[i].c_str());
            fprintf(asmCode, "%s\n", asmT->asmCode[i].c_str());
        }
        fclose(asmCode);
    }

    parserDestructor();

    analexDestructor();

    fclose(file);

    return EXIT_SUCCESS;
}
